<!--
*@Author: QWP
*@Description: 四川地图的3d
*@Date: 2024-10-10 16:36:14
-->
<template>
  <a-layout class="u-3d-map">
    <!-- 顶部工具 -->
    <TopAllData :data="topAllData"
      :isNext="isNext"
      @itemClick="showTopTypeFlag"
      @click="toParentMap"
      @search="companyTypeSearch"/>

    <!-- 地图区域 -->
    <div ref="mapContainer" id="mapContainer" style="width: 100%; height: 100%; overflow: hidden"
      v-if="refreshMap">
    </div>

    <!-- 图例 -->
    <!-- <Legend v-if="isNext == '2'"/> -->

    <!-- 地图高亮详细数据 -->
    <MapDetial :show="showMapDetial"
      :data="mapAllData"
      :loading="tipLoading"/>

    <!-- 非煤企业的风险详情 -->
    <template v-if="teamFirmDetialType == 'firm'">
      <NoCoalWarnDetial v-model:open="teamFirmDetialShow"
        :data="teamFirmDetial"
        @close="teamFirmDetial = {}"/>
    </template>

    <!-- 危化企业风险详情 -->
    <template v-if="teamFirmDetialType == 'endanger'">
      <EndangerFirmDetial v-model:open="teamFirmDetialShow"
        :data="teamFirmDetial"
        @close="teamFirmDetial = {}"/>
    </template>

    <!-- 地图的队伍详细信息 -->
    <template v-if="teamFirmDetialType == 'team'">
      <TeamFirmDetial :show="teamFirmDetialShow" 
        :data="teamFirmDetial" 
        :type="teamFirmDetialType"
        @close="teamFirmDetialShow = false; teamFirmDetial = {}, emits('click', fkRegionId)"/>
    </template>
        
    <!-- 安全生产的详情 -->
    <template v-if="teamFirmDetialType == 'security'">
      <SecurityDetial v-model:open="teamFirmDetialShow"
        :data="teamFirmDetial"
        @close="teamFirmDetial = {}"/>
    </template>

    <!-- 煤矿风险的详情 -->
    <template v-if="teamFirmDetialType == 'coal'">
      <CoalWarnDetial v-model:open="teamFirmDetialShow"
        :data="teamFirmDetial"
        @close="teamFirmDetial = {}"/>
    </template>
  </a-layout>
</template>

<script lang='ts' setup>
import { ref, reactive, computed, onMounted, nextTick } from 'vue' 
import axios from 'axios';
import * as THREE from 'three';
import { OrbitControls } from "three/examples/jsm/controls/OrbitControls";
import {
  CSS2DRenderer,
  CSS2DObject,
} from "three/addons/renderers/CSS2DRenderer.js";
import * as d3 from "d3";
import { urlFile, numberC } from '@/util/common';
import direction_img from '@/assets/map/direction.png'
import turn_img from '@/assets/map/turn.png'
import expand_circle_d from '@/assets/map/expand_circle_d.png'
import MapDetial from './MapDetial.vue';
import TeamFirmDetial from './TeamFirmDetial.vue'
import TopAllData from './TopAllData.vue';
import SecurityDetial from './securityDetial/Index.vue'
import CoalWarnDetial from './coalDetial/Index.vue'
import NoCoalWarnDetial from './noCoalDetial/Index.vue'
import EndangerFirmDetial from './endangerDetial/Index.vue'
import Legend from './Legend.vue'
import * as sumWarningApi from '@/service/emergency/sumWarning'
import * as resourceServe from "@/service/resource/index";
import * as businessDetailsAPI from '@/service/emergency/businessDetails';
import * as collieryInformationAPI from '@/service/emergency/collieryInformation';
import * as endangerWarningApi from '@/service/emergency/endanger'
import * as endangerFirmApi from '@/service/emergency/endangerFirm'
import * as TWEEN from '@tweenjs/tween.js'
import { cloneDeep } from "lodash";
import { addC } from '@/util/computePtrcision.ts';

const emits = defineEmits(['click'])

let textureLoader = new THREE.TextureLoader(); //纹理贴图加载器
let WaveMeshArr = []; //所有波动光圈集合
let rotatingApertureMesh, rotatingPointMesh;

// 墨卡托投影转换
const projection = d3.geoMercator();

let scene = null;
let camera = null;
let renderer = null;
let contant = null;
let spotLight = null;
let map = null;
let centerPos = [114.255221, 30.619014]; // 地图中心经纬度坐标
let raycaster = null; // 光线投射 用于进行鼠标拾取
let mouse = new THREE.Vector2(0, 0); // 鼠标位置
let labelRenderer = null; //CSS2DRenderer渲染器对象
let checkMesh = []; // 选中的元素
const mpColors = {
  mapColor: '#b8ddff',
  mapLightColor: '#2491f6',
  sideColor: '#d7e8f7'
}

// 顶部汇总数据
const isTopSearch = ref<boolean>(false)
const topAllCashData = ref<object>({})
const topAllData = ref<any[]>([
  { label: '队伍总数', value: 0, unit: '支', img: urlFile('map/flag/unfire.png'), borderColor: '#FFBE79', type: 'team', data: [] },
  { label: '预警企业总数', value: 0, unit: '家', img: urlFile('map/flag/firm.png'), borderColor: '#79BEFF', type: 'firm', data: [] },
  { label: '风险总数', value: 0, unit: '个', img: urlFile('map/flag/warn.png'), borderColor: '#FF7C83', type: 'warn', data: []},
])

// 地图鼠标移入的汇总数据
const showMapDetial = ref<boolean>(false)
const mapAllData = ref<any>({
  label: '',
  data: {
    team: {
      img: urlFile('map/flag/all_team.png'),
      title: '队伍总数',
      unit: '支', 
      bgColor: 'rgba(255,190,121,0.4)',
      value: ''
    },
    firm: {
      img: urlFile('map/flag/all_firm.png'),
      title: '企业总数',
      unit: '家', 
      bgColor: 'rgba(24,144,255,0.1)',
      value: ''
    },
    warn: {
      img: urlFile('map/flag/all_warn.png'),
      title: '风险总数',
      unit: '个', 
      bgColor: 'rgba(255,124,131,0.4)',
      value: ''
    },
  }
})

const refreshMap = ref<boolean>(true)
const detchMapData = ref<any[]>([])

const leadgensValues = ref<any[]>(['team', 'firm'])

// 用于缓存已获取的子级高亮数据
const tipLoading = ref<boolean>(false)
const tipAllData = ref<object>({})

let isNext = ref<string>('1')
let loading = ref<boolean>(false)

let maxScalc = ref<number>();
let nowScalc = ref<number>();
let isDrilling = ref<boolean>(false); // 地图下钻动画

// 地图的标点信息 regionId  team, firm, security, coal
const mapFlagData = ref<object>({})

// 二级地图，的图表点击展示的数据
const teamFirmDetialShow = ref<boolean>(false);
const teamFirmDetial = ref<any>({});
const teamFirmDetialType = ref<string>('');

// 地图是否完成缩放
const mapIsScaled = ref<boolean>(true)

onMounted(async () => {
  await getMapData()
  getAllWarnData()
  initMap()
})

// 获取全部的数据
// fkRegionId: 点击区域的code
// isLoadAll: 是否加载全部数据，包括顶部数据
// onlyViewFlag: 是否只加载地图标签
let fkRegionId = ref<string>('510000')
let companyType = ref<string>('')
const getAllWarnData = async (isLoadAll: boolean = true, onlyViewFlag: boolean = false) => {
  if(isLoadAll == true && onlyViewFlag == false) {
    topAllData.value.forEach(item => {
      item.value = 0;
      item.data = []
    })
  }

  // 清除以及地图的高亮提示信息
  for(let key in mapAllData.value.data) {
    mapAllData.value.data[key].value = 0
  }

  // 初始化对应的地图数据图表对象
  if(!mapFlagData.value[fkRegionId.value]) {
    mapFlagData.value[fkRegionId.value] = {}
  }

  // 非煤矿企业信息
  try {
    await getNoneCarbonData(isLoadAll);
  } catch (error) {}

  // 危化企业信息
  try {
    await getEndangerData(isLoadAll);
  } catch (error) {}

  // 队伍信息
  try {
    await getTeamData(isLoadAll);
  } catch (error) {}

  // 企业安全生产信息
  try {
    await getFirmSecurityData(isLoadAll)
    if(isNext.value != '1') {
      await getFirmSecurityLocationData()
    }
  } catch (error) {}

  // 煤矿风险
  try {
    // 煤矿只需在二级页面查询
    if(isNext.value != '1') {
      await getWarnCoalData(isLoadAll)
    }
  } catch (error) {}
  
  if(isNext.value != '1') {
    await new Promise((resolve, reject) => {
      if(mapIsScaled.value == true) {
        resolve()
      }
    })
    // 创建地图图标
    let tMapFlagData = mapFlagData.value[fkRegionId.value] || {};
    let teamAndFirmData = Object.values(tMapFlagData).flat(2)
    createFlagTeam(teamAndFirmData)
  }
}

// 获取非煤相关的数据
const getNoneCarbonData = async(isLoadAll: boolean = true) => {
  // 非煤、危化、煤矿的风险及企业总数
  tipLoading.value = true;
  try {
    const totalRes = await sumWarningApi.getWarnCount({ 
      fkRegionId: fkRegionId.value,
      companyType: companyType.value,
      _cancel: 1
    })
    if(totalRes.code == 0) {
      if(isLoadAll == true) {
        // 风险总数
        let warnIndex = topAllData.value.findIndex(i => i.type == 'warn');
        if(warnIndex != -1 && isTopSearch.value == false) {
          topAllData.value[warnIndex].value += numberC(totalRes.data['warnCount'])
        }

        // 企业总数
        let firmIndex = topAllData.value.findIndex(i => i.type == 'firm');
        if(firmIndex != -1 && isTopSearch.value == false) {
          topAllData.value[firmIndex].value += numberC(totalRes.data['companyCount'])
        }
      }
      // 一级地图高亮显示数据
      else {
        mapAllData.value.data.warn.value += numberC(totalRes.data['warnCount'])
        setAndGetTipMapData('warn', cloneDeep(mapAllData.value.data.warn), totalRes.originData.fkRegionId)
        
        mapAllData.value.data.firm.value += numberC(totalRes.data['companyCount'])
        setAndGetTipMapData('firm', cloneDeep(mapAllData.value.data.firm), totalRes.originData.fkRegionId)
      }
    }
  } catch (error) {}

  // 企业相关信息
  loading.value = true;
  try {
    const res = await sumWarningApi.getCompany({
      model: {
        keywords: null,
        fkRegionId: fkRegionId.value,
        companyType: companyType.value,
      },
      _cancel: 1,
      current: 1,
      size: 200000
    })
    if(res.code == 0) {
      let tData = res.data.records || []
      // 加载全部数据
      if(isLoadAll == true) {
        let index = topAllData.value.findIndex(i => i.type == 'firm');
        if(index != -1) {
          tData.forEach(item => {
            item.LONGITUDE = item.longitude
            item.LATITUDE = item.latitude
            item.FK_REGIONNAME = item.companyName
            item.NAME = item.companyName
            item.type = 'firm'
          })
          // 顶部数据
          topAllData.value[index].data = tData
        }
        // 地图标记数据
        mapFlagData.value[res.originData.model.fkRegionId].firm = tData;
      }
    }
  } catch (error) {}
  loading.value = false;
  tipLoading.value = false;
}

// 获取危化企业预警信息 -- 仅限地图二级标点信息
const getEndangerData = async() => {
  if(isNext.value == '1') {
    return
  }
  loading.value = true;
  tipLoading.value = true;
  try {
    const res = await endangerFirmApi.page({
      model: {
        keywords: null,
        fkRegionId: fkRegionId.value
      },
      _cancel: 1,
      current: 1,
      size: 20000
    })
    if(res.code == 0) {
      let tData = res.data.records || [];
      // if(isLoadAll == true) { 
        tData.forEach(item => {
          item.type = 'endanger';
          item.NAME = item.orgName;
          item.LONGITUDE = item.longitude;
          item.LATITUDE = item.latitude;
        })

        // 地图标记数据
        mapFlagData.value[res.originData.model.fkRegionId].endanger = tData;
      // }
    }
  } catch (error) {}
  loading.value = false;
  tipLoading.value = false;
}

// 获取队伍信息
const getTeamData = async(isLoadAll: boolean = true) => {
  loading.value = true;
  tipLoading.value = true;
  try {
    const res = await resourceServe.getTeams({
      model: { 
        fkRegionId: fkRegionId.value,
      },
      _cancel: 1,
      current: 1, 
      size: 200000
    })
    const { minLat, maxLat, minLon, maxLon } = getCenterMap()
    if(res.code == 0) {
      let tData = res.data.records || [];
      // 加载全部数据
      if(isLoadAll == true) { 
        tData.forEach(item => {
          item.type = 'team'
          item.NAME = item.TEAM_NAME;
          // return numberC(item.LONGITUDE) >= minLon && numberC(item.LONGITUDE) <= maxLon &&
          //        numberC(item.LATITUDE) >= minLat && numberC(item.LATITUDE) <= maxLat
        })
        let index = topAllData.value.findIndex(i => i.type == 'team');
        if(index != -1) { 
          topAllData.value[index].value = res.data.total
          topAllData.value[index].data = tData
        }
        // 地图标记数据
        mapFlagData.value[res.originData.model.fkRegionId].team = tData;
      }
      // 弹窗数据加载
      else {
        mapAllData.value.data.team.value = tData.length
        setAndGetTipMapData('team', cloneDeep(mapAllData.value.data.team), res.originData.model.fkRegionId)
      }
    }
  } catch (error) {}
  loading.value = false;
  tipLoading.value = false;
}

// 获取企业安全生产的以及地图信息
const getFirmSecurityData = async (isLoadAll: boolean = true) => {
  loading.value = true;
  tipLoading.value = true;
  let tFkRegionId = (fkRegionId.value+ '').replace(/00$/g, '')
  try {
    const res = await businessDetailsAPI.getTCompanyArchivesInfoHasHidTrbGroup({
      model: { 
        isHidTrb: 1,
        isHz: 1,
        sjareaId: tFkRegionId == '5100' ? '' : tFkRegionId,
        fkRegionId: fkRegionId.value
      },
      _cancel: 1,
      current: 1, 
      size: 200000
    })
    const { minLat, maxLat, minLon, maxLon } = getCenterMap()
    if(res.code == 0) {
      let tData = res.data.records || [];
      // 加载全部数据
      if(isLoadAll == true) {
        // 顶部的企业数量
        let index = topAllData.value.findIndex(i => i.type == 'firm');
        if(index != -1 && isTopSearch.value == false) {
          topAllData.value[index].value += numberC(tData[0]['cnum'])
        }

        // 顶部的风险总数
        let windex = topAllData.value.findIndex(i => i.type == 'warn');
        if(windex != -1  && isTopSearch.value == false) { 
          topAllData.value[windex].value += numberC(tData[0]['fxnum'])
        }
      }
      // 弹窗tip数据加载
      else {
        mapAllData.value.data.firm.value += numberC(tData[0]['cnum'])
        setAndGetTipMapData('firm', cloneDeep(mapAllData.value.data.firm), res.originData.model.fkRegionId)
        
        mapAllData.value.data.warn.value += numberC(tData[0]['fxnum'])
        setAndGetTipMapData('warn', cloneDeep(mapAllData.value.data.warn), res.originData.model.fkRegionId)
      }
    }
  } catch (error) {}
  loading.value = false;
  tipLoading.value = false;
}

// 获取企业安全生产的二级地图的定位信息
const getFirmSecurityLocationData = async () => {
  loading.value = true;
  tipLoading.value = true;
  try {
    const res = await businessDetailsAPI.getCompany({
      model: { 
        isHidTrb: 1,
        isHz: 0,
        sjareaId: (fkRegionId.value+ '').replace(/00$/g, ''),
        fkRegionId: fkRegionId.value
      },
      current: 1, 
      _cancel: 1,
      size: 200000
    })
    const { minLat, maxLat, minLon, maxLon } = getCenterMap()
    let tData = res.data.records || [];
    tData.forEach(item => {
      item.type = 'security'
      item.LONGITUDE = item.lon;
      item.LATITUDE = item.lat;
      item.NAME = item.entName;
      // return numberC(item.LONGITUDE) >= minLon && numberC(item.LONGITUDE) <= maxLon &&
      //        numberC(item.LATITUDE) >= minLat && numberC(item.LATITUDE) <= maxLat
    })

    // 地图标记数据
    mapFlagData.value[res.originData.model.fkRegionId].security = tData;
   
  } catch (error) {}
  loading.value = false;
  tipLoading.value = false;
}

// 获取二级地图的存在风险的煤矿信息
const getWarnCoalData = async(isLoadAll: boolean = true) => {
  console.log("🚀 ~ isLoadAll:", isLoadAll)
  loading.value = true;
  tipLoading.value = true;
  try {
    const res = await collieryInformationAPI.getCompany({
      model: { 
        type: 1,
        fkRegionId: fkRegionId.value || '510000',
      },
      _cancel: 1,
      current: 1, 
      size: 200000
    });
    if (res.code == 0) {
      let tData = res.data.records || [];
      // 二级地图
      if(isNext.value != '1') {
        const { minLat, maxLat, minLon, maxLon } = getCenterMap()
        tData.forEach(item => {
        // tData = tData.forEach(item => {
          item.type = 'coal'
          item.LONGITUDE = item.longitude;
          item.LATITUDE = item.latitude;
          item.NAME = item.name;
          // return numberC(item.LONGITUDE) >= minLon && numberC(item.LONGITUDE) <= maxLon &&
          //       numberC(item.LATITUDE) >= minLat && numberC(item.LATITUDE) <= maxLat
        })

        // 地图标记数据
        mapFlagData.value[res.originData.model.fkRegionId].coal = tData;
      }
    }
  } catch (error) {}
  loading.value = false;
  tipLoading.value = false;
}

// 初始化Threejs
const initMap = () => {
  // 第一步新建一个场景
  scene = new THREE.Scene();
  contant = document.getElementById("mapContainer");
  // scene.background = new THREE.Color("none");

  //环境光
  const ambient = new THREE.AmbientLight("#ffffff", 4);
  scene.add(ambient);

  setCamera();

  setRenderer();

  createMapBox()

  setController();

  createDireftionImg();

  createCircleImg()

  // createDynamicCircleImg()

  window.onresize = () => {
    renderer.setSize(
      contant.clientWidth,
      contant.clientHeight
    );
    camera.aspect = contant.clientWidth / contant.clientHeight;
    camera.updateProjectionMatrix();
  };

  // 设置滚轮缩放
  setMousWheel()

  // 地图下钻动画
  animate();

  // 场景渲染
  render();
}

// 新建透视相机
function setCamera() {
  camera = new THREE.PerspectiveCamera(
    50,
    contant.clientWidth / contant.clientHeight,
    1,
    1000
  );
  // 设置相机位置
  camera.position.set(3, 30, 30);
}

// 设置渲染器
function setRenderer() {
  renderer = new THREE.WebGLRenderer();
  // 设置画布的大小
  renderer.setSize(
    contant.clientWidth,
    contant.clientHeight
  );
  contant.appendChild(renderer.domElement);

  // 创建CSS2DRenderer渲染器
  labelRenderer = new CSS2DRenderer();
  // 设置labelRenderer渲染器宽高
  labelRenderer.setSize(
    contant.clientWidth,
    contant.clientHeight
  );
  labelRenderer.domElement.style.position = "absolute";
  labelRenderer.domElement.style.top = "0px";
  // 将渲染器添加到页面
  contant.appendChild(labelRenderer.domElement);
}

function render() {
  renderer.render(scene, camera);
  renderer.setClearAlpha(0.0);
  labelRenderer.render(scene, camera);
}

// 获取地图数据
async function getMapData(code = '510000', isInit: boolean = false) {
  try {
    if(scene) {
      clearOldMap()
    }
    const res = await axios.get(`https://geo.datav.aliyun.com/areas_v3/bound/${code}_full.json`)
    if(res.status == 200) {
      detchMapData.value = res.data.features;
      if(isInit == false) {
        createMapBox()
      }
    }
  } catch (error) {}

}

// 绘制地图
function createMapBox() {
  // 初始化一个地图对象
  map = new THREE.Object3D();
  let initScale = isNext.value == '1' ? 1 : 0.5
  map.scale.set(initScale, initScale, initScale)

  const { averageCoordinate, scaleMin } = getCenterMap()
  nowScalc.value = isNext.value == '1' ? scaleMin : (fkRegionId.value =='513300'? scaleMin + 80 : scaleMin + 100)
  maxScalc.value = scaleMin

  // 地理坐标数据 转换为3D坐标数据
  // 墨卡托投影转换
  projection.center(averageCoordinate).scale(nowScalc.value).translate([0, 0]);
  
  detchMapData.value.forEach((elem) => {
    const coordinates = elem.geometry.coordinates;
    const province = new THREE.Object3D();
    province.name = elem.properties.name;
    province.code = elem.properties.adcode;
    // 拉伸 地图厚度
    const depth = 1;
    //这里创建文字坐标
    const lightPoint = createMapLabel(elem.properties, depth);
    // 循环坐标数组
    coordinates.forEach((multiPolygon) => {
      multiPolygon.forEach((polygon) => {
        // 创建地图区块
        const mesh = createMesh(polygon, depth);

        // 创建地图区块边界线
        const line = createLine(polygon, depth);
        province.add(mesh, line, ...lightPoint);
      });
    });

    // 地图区块添加到地图对象中
    map.add(province);
  });

  map.name = 'map_box'

  // if(fkRegionId.value != '') {
    // isDrilling.value = true
  // }
  
  // 地图放到中心位置
  setCenter(map);
  
  // 地图添加到场景中
  scene.add(map);
  
  setClickFn();

  createFlagTeam()

  if(isNext.value != '1') {
    mapIsScaled.value = false;
    mapSacle()
  }
}

// 地图缩放动效
function mapSacle() {
  let initScale = 0.5;
  let timer = setInterval(() => {
    initScale += 0.004
    map.scale.set(initScale, initScale, initScale)
    if(initScale > 1) {
      clearInterval(timer)
      mapIsScaled.value = true
    }
  }, 0.1)
}

// 在每帧更新Tween动画
function animate() {
  requestAnimationFrame(animate);
  renderer.render(scene, camera);
}

// 创建公司、队伍的标记点
let leaClick = ref<number>(0)
function createFlagTeam(originData: any[] = []) {
  clearFlag()
 
  if(isNext.value == '1') {
    return
  }

  const setLabel = (tag, x, y, { data, type }) => {
    tag.style.position = "absolute";
    tag.addEventListener('mousedown', function(event) {
      teamFirmDetialType.value = type
      teamFirmDetial.value = data;
      teamFirmDetialShow.value = true;
      if(type == 'team') {
        emits('click', data, 'team')
      }
    })
    let label = new CSS2DObject(tag);
    label.element.style.visibility = "visible";

    let yRandom = 0

    label.position.set(x, -y+yRandom, 1.5);
    // label.position.set(x, -y, 0);
    label.name = 'map_flag';
    return label
  }

  map.children.forEach((item, index) => {
    if(index == 0) {
      originData.forEach(o => {
        const { LONGITUDE, LATITUDE, type, NAME } = o
        const [x, y] = projection([LONGITUDE, LATITUDE]);
        let tag = document.createElement("img");
        tag.style = "width: 25px; z-index: 200"
        tag.title = NAME;
        // tag.innerText = NAME;

        if(type == 'team') {
          tag.src = urlFile('map/flag/map_team2.png');
          item.add(setLabel(tag, x, y, { data: o, type: 'team' }));
        }
        // 非煤矿企业
        else if(type == 'firm') {
          tag.src = urlFile('map/flag/flag_no_coal.png');
          tag.style.width = "32px"
          item.add(setLabel(tag, x, y, { data: o, type: 'firm' }));
        }
        // 危化企业
        else if(type == 'endanger') {
          tag.src = urlFile('map/flag/flag_endanger.png');
          tag.style.width = "32px"
          item.add(setLabel(tag, x, y, { data: o, type: 'endanger' }));
        }
        // 安全企业生产
        else if(type == 'security') {
          tag.src = urlFile('map/flag/flag_security.png');
          tag.style.width = "32px"
          item.add(setLabel(tag, x, y, { data: o, type: 'security' }));
        }
        // 煤矿
        else if(type == 'coal') {
          tag.src = urlFile('map/flag/flag_coal.png');
          tag.style.width = "32px"
          item.add(setLabel(tag, x, y, { data: o, type: 'coal' }));
        }
      })
    }
  })

  render()
}

// 清除地图上的图表标记
function clearFlag() {
  for(let i = 0; i < map.children.length; i++) {
    if(i != 0) {
      continue;
    }
    for(let j = map.children[0].children.length - 1; j >= 0; j--) {
      if(map.children[0].children[j].name == 'map_flag') {
        map.children[0].remove(map.children[0].children[j])
      }
    }
  }
}

// 创建文字坐标
function createMapLabel(properties, depth) {
  let lightCenter = properties.centroid || properties.center;
  let areaName = properties.name;
  // projection用来把经纬度转换成坐标
  const [x, y] = projection(lightCenter);
  //这里创建文字坐标
  const label = createTextPoint(x, y, areaName, depth);
  return [label];
}

/**
 * @description 创建文字坐标
 * @param {*} x d3 - 经纬度转换后的x轴坐标
 * @param {*} y d3 - 经纬度转换后的y轴坐标
 * @param {*} areaName 地名
 */
function createTextPoint(x, y, areaName, depth) {
  let tag = document.createElement("div");
  tag.innerHTML = areaName;
  tag.style = `position: absolute; color:#333; font-size: 12px`;
  tag.addEventListener('mousemove', function(event) {
    mouseMoveMapItem(event)
  })
  let label = new CSS2DObject(tag);
  label.element.style.visibility = "visible";
  label.position.set(x, -y, depth);
  return label;
}

// 创建方向图片
function createDireftionImg() {
  const { averageCoordinate, scaleMin } = getCenterMap()
  const [x, y] = projection(averageCoordinate);
  const geometry = new THREE.CircleGeometry( 20, 1000 );
  const material = new THREE.MeshBasicMaterial( {
    map: textureLoader.load(direction_img),
    transparent: true
  } );
  const circle = new THREE.Mesh( geometry, material );
  circle.rotateZ(25.2)
  circle.rotateX(18.2)
  circle.position.x = -2
  scene.add( circle );
}

// 创建旋转图片
let circleImg = null;
function createCircleImg() {
  const geometry = new THREE.CircleGeometry( 22, 1000 );
  const material = new THREE.MeshBasicMaterial( {
    map: textureLoader.load(turn_img),
    transparent: true
  } );
  circleImg = new THREE.Mesh( geometry, material );
  circleImg.rotateZ(25.2)
  circleImg.rotateX(18.2)
  circleImg.position.x = -2
  scene.add( circleImg );

  // 开始动画循环
  CircleAnimation();
}

// 创建动效圈层
let expandCircleDdImg = null
function createDynamicCircleImg() {
  const geometry = new THREE.CircleGeometry( 14, 1000 );
  const material = new THREE.MeshBasicMaterial( {
    map: textureLoader.load(expand_circle_d),
    // transparent: true,
    // opacity: 1
  });
  expandCircleDdImg = new THREE.Mesh( geometry, material );
  expandCircleDdImg.rotateZ(25.2)
  expandCircleDdImg.rotateX(18.2)
  expandCircleDdImg.position.x = -2
  scene.add( expandCircleDdImg );
}


let diffTime = 60; // 动画最小时间间隔,单位 ms
let lastDate = Date.now() // 上次时间 - 初始记录的当前时间
function slowRateAnimation(animateFn: Function) {
  // 运动时间
  let currentDate = Date.now()
  if (currentDate - lastDate >= diffTime) {
      lastDate = currentDate

      animateFn()
  }
}

// 背景旋转图
function CircleAnimation() {
  
  let animate = function(){
    // 旋转立方体
    circleImg.rotation.z += 0.005;
    
    render()
  } 

  // 指定动画频率降低
  slowRateAnimation(animate)

  // 定义动画函数
  requestAnimationFrame(CircleAnimation);
  
}

// 点击事件
let beforeMapList = []; // 上一次处理的地图块列表
function setClickFn() {
  raycaster = new THREE.Raycaster();
  mouse = new THREE.Vector2();

  const content = document.getElementById("mapContainer")

  // 点击事件
  content.addEventListener("mousedown", async function(event) {
    event.stopPropagation()
    const mapList = getSelMap(event)

    if(!mapList || mapList.length == 0) {
      return
    }
    if(mapList[0].object.name != '地图区域') {
      return
    }
    if(mapList.length != 0 && isNext.value == '1') {
      isNext.value = '2';
      let code = (mapList[0].object.parent.code || '') + ''
      if(code) {
        
        await getMapData(code)
        
        fkRegionId.value = isNext.value == '1' ? code.substring(0, 4) + '00' : code;

        emits('click', fkRegionId.value, 'map')
        
        getAllWarnData(true)
      }
    }
  }, false);
  
  // 鼠标移动事件  tip
  content.addEventListener("mousemove", function(event) {
    mouseMoveMapItem(event)
  });

}

// 设置鼠标移入的设置
function mouseMoveMapItem(event) {
  event.stopPropagation()
  const mapList = getSelMap(event) || []

  hoverMapColor(mapList)

  if(mapList.length != 0) {
    if(isNext.value == '2') {
      showMapDetial.value = false;
      return
    }
    if(mapList[0].object.name != '地图区域') {
      return
    }
    showMapDetial.value = true;
    let code = (mapList[0].object.parent.code || '') + ''
    fkRegionId.value = isNext.value == '1' ? code.substring(0, 4) + '00' : code;
    if(mapAllData.value.label != mapList[0].object.parent.name) {
      let cashData = setAndGetTipMapData('', [], fkRegionId.value)
      cashData && Object.keys(cashData['data'] || {}).length == 3 ? mapAllData.value = cashData : getAllWarnData(false)
    }
    mapAllData.value.label = mapList[0].object.parent.name || ''
  }
  else if(mapList.length == 0){
    showMapDetial.value = false;
  }
}

// 鼠标移入的颜色及变化
function hoverMapColor(mapList) {
  // 上次选中的元素恢复初始颜色
  beforeMapList.forEach((bMap) => {
    if(bMap.object.name == '地图区域') {
      bMap.object.material[0].color.set(mpColors.mapColor);
      if(bMap.object.parent) {
        bMap.object.parent.children.forEach((child) => {
          if(child.isCSS2DObject == true) {
            child.element.style.color = "#333"
          }
          child.scale.z = 1
        })
      }
    }
  });

  // 激活元素改变颜色
  let firstCityName = '';
  mapList.forEach((map1) => {
    if(!firstCityName) {
      firstCityName = map1.object.parent.name
    }
    if(firstCityName == map1.object.parent.name && map1.object.name == '地图区域') {
      map1.object.material[0].color.set(mpColors.mapLightColor);
      map1.object.parent.children.forEach((child) => {
        if(child.isCSS2DObject == true) {
          child.element.style.color = "#fff"
        }
        child.scale.z = 2
      })
    }
  });

  if(mapList.length != 0) {
    beforeMapList = mapList;
  }
}

// 查看点击区域的汇总数据
function showClickDetialData(mapList) {
  try {
    let tag = document.createElement("div");
    tag.style = `
      position: absolute;
      padding: 20px;
      width: 400px;
      background: linear-gradient( 169deg, rgba(199,228,255,0.8) 0%, rgba(249,252,255,0.8) 100%);
      border-radius: 16px 16px 16px 16px;
      border: 2px solid #FFFFFF;`
    
    let title = document.createElement("div")
    title.innerText = mapList[0].object.parent.name;
    title.style = `
      font-family: PingFang SC Medium, PingFang SC Medium;
      font-weight: 400;
      font-size: 16px;
      color: #333333;
      line-height: 22px;
      text-align: left;
      font-style: normal;
      text-transform: none;
    `
    tag.appendChild(title)

    let contentBox = document.createElement("div");
    contentBox.classList.add("u-tip-all-content-box")
    contentBox.style = ``
    contentBox.appendChild(createAllDetialItem({}, 'team'))
    contentBox.appendChild(createAllDetialItem({}, 'firm'))
    contentBox.appendChild(createAllDetialItem({}, 'warn'))
    tag.appendChild(contentBox)
  
    let label = new CSS2DObject(tag);
    label.element.style.visibility = "visible";
    label.position.z = 8;
    label.position.y = 8;
    label.name = 'all_sum';
    scene.add(label);
  } catch (error) {}
}

// 绘制总数的具体项数据
function createAllDetialItem(data, type,) {
  let box = document.createElement("div");
  box.classList.add("u-tip-detial-item")
  box.style = `display: flex; flex-direction: column; padding-top: 20px;`;

  const origin = {
    team: {
      img: urlFile('map/flag/all_team.png'),
      title: '队伍总数',
      unit: '支', bgColor: 'rgba(255,190,121,0.4)'
    },
    firm: {
      img: urlFile('map/flag/all_firm.png'),
      title: '企业总数',
      unit: '家', bgColor: 'rgba(24,144,255,0.1)'
    },
    warn: {
      img: urlFile('map/flag/all_warn.png'),
      title: '风险总数',
      unit: '个', bgColor: 'rgba(255,124,131,0.4)'
    },
  }

  const { img, title, unit, bgColor } = origin[type]

  box.innerHTML = `
    <div style='display: flex; justify-content: center; align-items: center; 
      width: 48px; height: 48px;
      background: ${ bgColor }; border-radius: 16px 16px 16px 16px;'>
      <img src="${img}" width="30px" height="30px"/> 
    </div>
    <div style='margin-top: 16px; font-family: PingFang SC, PingFang SC;
      font-weight: 400;
      font-size: 14px;
      color: #666666;'>${ title }
    </div>
    <div style="margin-top: 8px">
      <span style='font-family: DIN, DIN;
        font-weight: 500;
        font-size: 18px;
        color: #333333;'>3000
      </span>
      <span style='font-family: font-family: DIN, DIN;
        font-weight: 400;
        font-size: 12px;
        font-weight: 500;
        font-size: 18px;
        color: #666666;'>${unit}</span>
    </div>
  `
  return box
}

// 获取鼠标触发过的地图信息
const getSelMap = (mouseEvent) => {
  try {
    const pointer = new THREE.Vector2();

    const content = document.getElementById("mapContainer")
  
    // pointer.x = (mouseEvent.offsetX / mouseEvent.target.clientWidth) * 2 - 1;
    // pointer.y = -(mouseEvent.offsetY / mouseEvent.target.clientHeight) * 2 + 1;
  
    pointer.x = (mouseEvent.offsetX / content.clientWidth) * 2 - 1;
    pointer.y = -(mouseEvent.offsetY / content.clientHeight) * 2 + 1;
  
    raycaster.setFromCamera(pointer, camera);
  
    const intersects = raycaster.intersectObjects(scene.children);

    return intersects;
  } catch (error) {}
  return null
};

// 设置最大旋转的角度
function setController() {
  let controls = new OrbitControls(camera, contant);
  controls.enableZoom = true;
  controls.maxPolarAngle = 2;
  controls.minPolarAngle = 1;
  controls.maxAzimuthAngle = 1;
  controls.minAzimuthAngle = -1;
  controls.addEventListener("change", (e) => {
    const newPosition = new THREE.Vector3();
    newPosition.setFromMatrixPosition(map.matrixWorld);
    map.position.copy(newPosition);

    renderer.render(scene, camera);
  });
}

// 创建地图区块网格模型
function createMesh(data, depth) {
  // 创建一个多边形轮廓
  const shape = new THREE.Shape();

  // 循环多边形坐标数组  polygon是地图区块的经纬度坐标数组
  for (let i = 0; i < data.length; i++) {
    const [x, y] = projection(data[i]);
    if (i === 0) {
      shape.moveTo(x, -y);
    }
    shape.lineTo(x, -y);
  }

  // 拉伸参数
  const extrudeSettings = {
    depth: depth, // 拉伸度 （3D地图厚度）
    bevelEnabled: false, // 是否使用倒角
  };

  // 将多边形 拉伸扫描成型  //shape二维轮廓  //extrudeSettings拉伸参数
  const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);
  geometry.computeBoundingBox();

  // 创建高光材质
  const material = new THREE.MeshBasicMaterial({
    color: mpColors.mapColor,
    opacity: 1,
  });

  // 创建基础网格材质
  const material1 = new THREE.MeshBasicMaterial({
    color: mpColors.sideColor,
    // transparent: true,
    // opacity: 0.9,
  });

  // 多边形添加材质
  const mesh = new THREE.Mesh(geometry, [
    material, // 表面
    material1, // 侧面
  ]);
  mesh.name = "地图区域";
  return mesh;
}

// 创建地图区块边界线
function createLine(data, depth) {
  // 线材质对象 创建地图边界线 白色
  const lineMaterial = new THREE.LineBasicMaterial({
    color: "white",
    linewidth: 8
  });
  // 创建一个空的几何体对象
  const lineGeometry = new THREE.BufferGeometry();
  const pointsArray = new Array();
  // 循环多边形坐标数组  polygon是地图区块的经纬度坐标数组
  for (let i = 0; i < data.length; i++) {
    const [x, y] = projection(data[i]);
    // 三维向量对象  用于绘制边界线
    pointsArray.push(new THREE.Vector3(x, -y, 0));
  }
  // setFromPoints方法从pointsArray中提取数据改变几何体的顶点属性vertices
  // 如果几何体是BufferGeometry，setFromPoints方法改变的是.attributes.position属性
  lineGeometry.setFromPoints(pointsArray);

  const line = new THREE.Line(lineGeometry, lineMaterial);
  line.position.z += depth + 0.001;
  line.name = "地图边界线";
  return line;
}

// 设置地图中心位置
function setCenter(map) {
  map.rotation.x = -Math.PI / 4;
  // 把地图放到"盒子"里面
  const box = new THREE.Box3().setFromObject(map);
  
  // 获取盒子中心点
  const center = box.getCenter(new THREE.Vector3());
  const offset = [0, 0];

  // 设置地图偏移  放到中心位置
  map.position.x = map.position.x - center.x - offset[0];
  map.position.z = map.position.z - center.z - offset[1];
}

// 地图下钻动画
function mapDrillanimate() {
  requestAnimationFrame(mapDrillanimate);
  const { averageCoordinate } = getCenterMap()

  if(isDrilling.value == true) {
    if(nowScalc.value < maxScalc.value) {
      nowScalc.value += 5;
      projection.center(averageCoordinate).scale(nowScalc.value).translate([0, 0]);
    }
    else {
      isDrilling.value = false;
    }
  }
  renderer.render(scene, camera);
}

// 地图下钻先清理原有数据
const clearOldMap = (mapListm, parent) => {
  for(let i = map.children.length - 1; i >= 0; i--) {
    for(let j = map.children[i].children.length - 1; j >= 0; j--) {
      map.children[i].remove(map.children[i].children[j])
    }
  }
}

// 点击交互 改变选中区域样式
function changeMesh(newVal) {
  // 变量地图模块
  map.children.map((item) => {
    if (item.type == "Object3D") {
      // 找到点击区域的父级元素
      if (item.uuid == newVal.parent.uuid) {
        // 改变Z坐标位置
        item.position.z = 0.5;
        // 遍历子元素
        item.children.map((element) => {
          if (element.type == "Mesh") {
            // 修改所有的区域颜色  黄色
            element.material[0].color.set(0xfeea37);
            // 侧边 深黄色
            element.material[1].color.set(0xa5960b);
          }
        });
      } else {
        // 还原位置
        item.position.z = 0;
        item.children.map((element) => {
          if (element.type == "Mesh") {
            // 还原区域颜色
            element.material[0].color.set(0x7bc6c2);
            element.material[1].color.set(0x123024);
          }
        });
      }
    }
    return item;
  });
}

// 根据企业类型赛选
const companyTypeSearch = async (companyType1) => {
  let tempFlagData = cloneDeep(mapFlagData.value[fkRegionId.value])
  mapFlagData.value[fkRegionId.value] = {
    team: tempFlagData['team'] || []
  };

  // 顶部企业类型筛选
  isTopSearch.value = true;

  switch(companyType1) {
    case '1': // 非煤
      await getNoneCarbonData(true)
      break
    case '2': // 煤矿
      await getWarnCoalData(true)
      break
    case '3': // 危化
      await getEndangerData(true)
      break
    case '4': // 安全生产检查隐患
      await getFirmSecurityData(true)
      if(isNext.value != '1') {
        await getFirmSecurityLocationData()
      }
      break
    default:
      getAllWarnData(true)
    
    isTopSearch.value = false
  }

  // 创建地图图标
  let tMapFlagData = mapFlagData.value[fkRegionId.value] || {};
  let teamAndFirmData = Object.values(tMapFlagData).flat(2)
  createFlagTeam(teamAndFirmData)
}

// 返回上级地图
async function toParentMap() {
  isNext.value = '1'
  fkRegionId.value = '510000'
  
  companyType.value = ''
  isTopSearch.value = false

  emits('click', fkRegionId.value, 'map')
  clearFlag() // 清除标记
  await getMapData()
  getAllWarnData(true)
}

// 顶部总数据过滤地图的标点
let nowTopTypeFlag = ref<string>('')
function showTopTypeFlag(data) {
  let result = []
  let tMapFlagData = cloneDeep(mapFlagData.value[fkRegionId.value] || {});
  if(nowTopTypeFlag.value != data.type) {
    // 只显示队伍信息标点
    if(data.type == 'team') {
      result = tMapFlagData['team'] || []
    }
    else if(data.type == 'firm') {
      delete tMapFlagData['team']
      result = Object.values(tMapFlagData).flat(2)
    }
    else {
      result = Object.values(tMapFlagData).flat(2)
    }
    nowTopTypeFlag.value = data.type
  }
  else {
    result = Object.values(tMapFlagData).flat(2)
    nowTopTypeFlag.value = ''
  }
  createFlagTeam(result)
}

// 计算中心及缩放
function getCenterMap() {
  let minLat = Infinity
  let maxLat = -Infinity
  let minLon = Infinity
  let maxLon = -Infinity
  // 获取所有坐标点
  const allCoordinates = []
  detchMapData.value.forEach((elem) => {
    const coordinates = elem.geometry.coordinates
    coordinates.forEach((multiPolygon) => {
      multiPolygon.forEach((polygon) => {
        allCoordinates.push(...polygon)
        for (let i = 0; i < polygon.length; i++) {
          const [x, y] = polygon[i]
          minLon = Math.min(minLon, x)
          maxLon = Math.max(maxLon, x)
          minLat = Math.min(minLat, y)
          maxLat = Math.max(maxLat, y)
        }
      })
    })
  })
  const container = document.getElementById("mapContainer")
  const scaleX = container.clientWidth / (maxLat - minLat)
  const scaleY = container.clientHeight / (maxLon - minLon)
  const scaleMin = Math.max(scaleX, scaleY) + 50

  // 计算坐标点的平均值
  const averageCoordinate = allCoordinates.reduce(
    (acc, coordinate) => {
      return [
        acc[0] + coordinate[0] / allCoordinates.length,
        acc[1] + coordinate[1] / allCoordinates.length
      ]
    },
    [0, 0]
  )
  return { averageCoordinate, scaleMin, minLat, maxLat, minLon, maxLon }
}

// 设置获取最新的地图高亮数据
const setAndGetTipMapData = (key?: string, data?: any, fkRegionId?: string) => {
  if(key) {
    if(!tipAllData.value[fkRegionId] && fkRegionId) {
      tipAllData.value[fkRegionId] = {
        label: mapAllData.value.label,
        data: {}
      }
    }
    tipAllData.value[fkRegionId].data[key] = data
  }
  else {
    return tipAllData.value[fkRegionId] || null
  }
}

// 设置滚轮缩放
const setMousWheel = () => {
  const content = document.getElementById("mapContainer")
  content.addEventListener('mousewheel', onDocumentMouseWheel, false);
  content.addEventListener('DOMMouseScroll', onDocumentMouseWheel, false); 
}

// 监听滚轮事件来实现缩放
let zoomLevel = 50;
let fov = 40;
let far = 1000;
let near = 1;
const onDocumentMouseWheel = (e) => {
  e.stopPropagation();
  if (e.wheelDelta) {  //判断浏览器IE，谷歌滑轮事件
    if (e.wheelDelta > 0) { //当滑轮向上滚动时
      fov -= (near < fov ? 1 : 0);
    }
    if (e.wheelDelta < 0) { //当滑轮向下滚动时
      fov += (fov < far ? 1 : 0);
    }
  } else if (e.detail) {  //Firefox滑轮事件
    if (e.detail > 0) { //当滑轮向上滚动时
        fov -= 1;
    }
    if (e.detail < 0) { //当滑轮向下滚动时
        fov += 1;
    }
  }
  camera.fov = fov;
  camera.updateProjectionMatrix();
  renderer.render(scene, camera);
}

</script>

<style lang='scss' >
.u-3d-map {
  position: relative;
  width: 100%;
  height: 100%;
}
.u-leagen-active {
  color: #1890FF
}

</style>